﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Dynamic;
using System.Linq;
using Enferno.Public.InversionOfControl;

namespace Enferno.Public.Web.ViewModels
{
    public class ProductViewModel : ProductBaseViewModel<VariantViewModel, FileViewModel, ParametricViewModel, ParametricValueViewModel>
    {
        
    }


    public class ProductBaseViewModel<TVariantViewModel, TFileViewModel, TParametricViewModel, TParametricValueViewModel> : BaseViewModel
        where TVariantViewModel: VariantBaseViewModel<TFileViewModel, TParametricViewModel, TParametricValueViewModel> 
        where TFileViewModel: FileViewModel
        where TParametricViewModel: ParametricBaseViewModel<TParametricValueViewModel>, new()
        where TParametricValueViewModel: ParametricValueViewModel, new()
    {
        public ProductBaseViewModel()
        {
            Flags = new List<int>();
            Files = new List<TFileViewModel>();
            _variantParametrics = new List<TParametricViewModel>();
            _variants = new List<TVariantViewModel>();
        }

        public int Id { get; set; }
        public string Description { get; set; }
        public string DescriptionHeader { get; set; }
        public List<int> Flags { get; set; }
        public string Name { get; set; }
        public string UnitOfMeasurement { get; set; }
        public OnHandStatus OnHandStatus { get; set; }
        public string OnHandStatusText1 { get; set; }
        public string OnHandStatusText2 { get; set; }
        public decimal OnHandStatusCount { get; set; }
        public decimal DisplayPrice { get; set; }
        public decimal CatalogPrice { get; set; }
        public decimal VatRate { get; set; }
        public int PriceListId { get; set; }
        public decimal RecommendedQuantity { get; set; }
        public int StatusId { get; set; }
        public string SubHeader { get; set; }
        public string UniqueName { get; set; }
        public List<TFileViewModel> Files { get; set; }

        private List<TParametricViewModel> _variantParametrics; 
        public List<TParametricViewModel> VariantParametrics
        {
            get { return _variantParametrics; }
            set { _variantParametrics = value; }
        }

        private List<TVariantViewModel> _variants;
        public List<TVariantViewModel> Variants
        {
            get { return _variants; }
            set { _variants = value; }
        }

        public TFileViewModel DefaultImage
        {
            get { return Files.First(file => file.Type == ProductFileType.DefaultImage); }
        }

        public IEnumerable<TFileViewModel> AdditionalImages
        {
            get { return Files.Where(file => file.Type == ProductFileType.AdditionalImage); }
        } 

        public bool HasVariantParametric(int parametricId, IEnumerable<TParametricViewModel> parametricsToChooseFrom = null)
        {
            if (parametricsToChooseFrom == null)
                parametricsToChooseFrom = VariantParametrics;

            return parametricsToChooseFrom.Any(variantParametric => variantParametric.Id == parametricId);
        } 

        public IEnumerable<TParametricValueViewModel> GetDistinctValuesForVariantParametric(int parametricId)
        {
            var variantParametricsToChooseFrom = VariantParametrics;

            if (HasVariantsButNoVariantParametrics())
                variantParametricsToChooseFrom = GetVariantParametricsForVariantsWithNoVariantParametrics();

            if (!HasVariantParametric(parametricId, variantParametricsToChooseFrom)) return new List<TParametricValueViewModel>();

            var variantParametric = variantParametricsToChooseFrom.Single(parametric => parametric.Id == parametricId);
            return variantParametric.Values;

        }

        private List<TVariantViewModel> GetVariantsForVariantsWithNoVariantParametrics()
        {
            var variantsWithFakeParametricAdded = _variants.Select(variant =>
            {
                var parametric = new TParametricViewModel
                {
                    Id = -1,
                    Values = new List<TParametricValueViewModel>
                    {
                        new TParametricValueViewModel {Value = variant.Name}
                    }
                };

                variant.VariantParametrics = new List<TParametricViewModel> {parametric};

                return variant;
            });
            return new List<TVariantViewModel>(variantsWithFakeParametricAdded);
        } 

        private List<TParametricViewModel> GetVariantParametricsForVariantsWithNoVariantParametrics()
        {
            var fakeParametric = new TParametricViewModel() { Id = -1 };
            var fakeParametricValues = _variants.Select(variant => new TParametricValueViewModel() {Value = variant.Name}).ToList();

            fakeParametric.Values = fakeParametricValues;

            return new List<TParametricViewModel>(){fakeParametric} ;
        }

        private bool HasVariantsButNoVariantParametrics()
        {
            return _variants.Count > 1 && _variantParametrics.Count == 0;
        }

    }
}
